package com.zhiyou.app.service.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.TypeReference;
import cn.hutool.core.map.MapUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zhiyou.app.common.constant.OrderTaskCacheMapping;
import com.zhiyou.app.common.constant.UserHandler;
import com.zhiyou.app.common.exception.BizException;
import com.zhiyou.app.common.util.JsonFileReader;
import com.zhiyou.app.common.util.ObjSorterUtil;
import com.zhiyou.app.common.util.SseEmitterSender;
import com.zhiyou.app.config.ordertaskhandler.BaseOrderTaskHandler;
import com.zhiyou.app.config.ordertaskhandler.OrderTaskHandlerHelper;
import com.zhiyou.app.mapper.TaskMapper;
import com.zhiyou.app.pojo.bo.TaskResult;
import com.zhiyou.app.pojo.entity.GoodsEntity;
import com.zhiyou.app.pojo.entity.OrderEntity;
import com.zhiyou.app.pojo.entity.OrderGoodsEntity;
import com.zhiyou.app.pojo.entity.TaskEntity;
import com.zhiyou.app.pojo.enums.OrderStatusEnum;
import com.zhiyou.app.pojo.vo.TaskResponseVo;
import com.zhiyou.app.service.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;

import static com.zhiyou.app.pojo.enums.TaskStatusEnum.*;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author jonathan.z
 * @since 2025-07-03
 */
@Slf4j
@Service
public class TaskServiceImpl extends ServiceImpl<TaskMapper, TaskEntity> implements ITaskService {
    @Resource
    private IOrderService orderService;
    @Resource
    private IOrderGoodsService orderGoodsService;
    @Resource
    private ComfyUIService comfyUIService;
    @Resource
    private IGoodsService goodsService;
    @Resource
    private ITaskService taskService;
    @Resource
    private JsonFileReader jsonFileReader;
    @Resource
    private OrderTaskHandlerHelper orderTaskHandlerHelper;
    @Resource
    private OrderTaskCacheMapping orderTaskCacheMapping;

    @Override
    public List<TaskResponseVo> createTask(String orderNum) {
        List<TaskResponseVo> taskResponseVos = new ArrayList<>();
        OrderEntity one = orderService.getOne(new LambdaQueryWrapper<OrderEntity>().eq(OrderEntity::getOrderNum, orderNum));
        if (one == null) {
            throw new BizException("订单不存在");
        }
        if (taskService.count(new LambdaQueryWrapper<>(TaskEntity.class).eq(TaskEntity::getOrderNum, orderNum)) > 0) {
            throw new BizException("订单任务已存在");
        }
        List<OrderGoodsEntity> ogList = orderGoodsService.list(new LambdaQueryWrapper<OrderGoodsEntity>().eq(OrderGoodsEntity::getOrderNum, orderNum));
        List<Integer> goodsIds = ogList.stream().map(OrderGoodsEntity::getGoodsId).collect(Collectors.toList());
        if (goodsIds.isEmpty()) {
            throw new BizException("订单商品不存在");
        }
        //按顺序提交任务，任务有先后
        List<TaskEntity> taskEntities = ObjSorterUtil.sortByOrder(goodsService.listByIds(goodsIds), goodsIds, GoodsEntity::getId).stream().map(goods -> {
            TaskEntity taskEntity = new TaskEntity();
            taskEntity.setOrderNum(orderNum);
            taskEntity.setTaskDesc(goods.getGoodsName());
            taskEntity.setTaskType(goods.getGoodsCode());
            taskEntity.setTaskStatus(CREATE);
            taskEntity.setUserId(one.getUserId());
            return taskEntity;
        }).collect(Collectors.toList());
        saveBatch(taskEntities);
        taskEntities.forEach(taskEntity -> {
            try {
                submitTask(taskEntity, one.getOrderParam());
            } catch (IOException e) {
                throw new BizException("订单" + orderNum + "任务[" + taskEntity.getTaskType() + "]提交失败");
            }
            taskResponseVos.add(new TaskResponseVo().setTaskId(taskEntity.getId()).setTaskDesc(taskEntity.getTaskDesc()).setOrderNum(taskEntity.getOrderNum()).setTaskPid(taskEntity.getTaskPid()));
        });
        taskResponseVos.forEach(taskResponseVo -> {
            orderTaskCacheMapping.putOrderNumByPid(taskResponseVo.getTaskPid(), taskResponseVo.getOrderNum());
        });
        return taskResponseVos;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void timerGetTaskResult() {
        LambdaQueryWrapper<TaskEntity> query = new LambdaQueryWrapper<TaskEntity>().eq(TaskEntity::getTaskStatus, PROCESSING).gt(TaskEntity::getCreateTime, DateUtil.offsetMinute(new Date(), -60));
        List<TaskEntity> list = taskService.list(query);
        if (!list.isEmpty()) {
            list.forEach(t -> {
                TaskResult taskResult = taskService.getOrderTaskCombineResult(t.getOrderNum());
                if (taskResult.isFinished()) {
                    t.setTaskResult(JSONUtil.toJsonStr(taskResult));
                    t.setTaskStatus(COMPLETE);
                }
            });
            taskService.updateBatchById(list);
            orderService.update(new LambdaUpdateWrapper<OrderEntity>().in(OrderEntity::getOrderNum, list.stream().map(TaskEntity::getOrderNum).collect(Collectors.toList())).set(OrderEntity::getOrderStatus, OrderStatusEnum.FINISHED));
        }
        query = new LambdaQueryWrapper<TaskEntity>().in(TaskEntity::getTaskStatus, Arrays.asList(PROCESSING, CREATE)).lt(TaskEntity::getCreateTime, DateUtil.offsetMinute(new Date(), -60));
        taskService.list(query).forEach(t -> {
            t.setTaskStatus(ERROR);
            if (t.getTaskStatus() == PROCESSING) {
                t.setTaskError("任务超时");
            } else if (t.getTaskStatus() == CREATE) {
                t.setTaskError("任务创建失败");
            }
            taskService.updateById(t);
        });
    }

    @Override
    public TaskResult getOrderTaskCombineResult(String orderNum) {
        List<TaskEntity> list = taskService.list(new LambdaQueryWrapper<TaskEntity>().eq(TaskEntity::getOrderNum, orderNum));
        return combineTaskResult(list.stream().map(t -> taskService.getTaskResult(t)).collect(Collectors.toList()));
    }

    @Override
    public TaskResult getTaskResult(TaskEntity taskEntity) {
        TaskResult taskResult = new TaskResult();
        String taskResultParam;
        boolean updateFlag = false;
        Map<String, Object> parseConfig = MapUtil.<String, Object>builder().build();
        OrderGoodsEntity one = orderGoodsService.getOne(new LambdaQueryWrapper<OrderGoodsEntity>().eq(OrderGoodsEntity::getOrderNum, taskEntity.getOrderNum()).eq(OrderGoodsEntity::getGoodsCode, taskEntity.getTaskType()));
        parseConfig.put(one.getGoodsCode(), one.getPaid());
        parseConfig.put("orderNum", taskEntity.getOrderNum());
        if (taskEntity.getTaskStatus() == COMPLETE) {
            taskResultParam = taskEntity.getTaskResult();
            taskResult = orderTaskHandlerHelper.getOrderTaskHandler(taskEntity.getTaskType()).parseResult(JSONUtil.toBean(taskResultParam, new TypeReference<Map<String, List<String>>>() {
            }, true), parseConfig);
            if (taskResult == null) {
                taskResult = new TaskResult().setFinished(false).setOrderNum(taskEntity.getOrderNum());
            }

        } else if (taskEntity.getTaskStatus() == PROCESSING && taskEntity.getTaskResult() != null) {
            taskResult = orderTaskHandlerHelper.getOrderTaskHandler(taskEntity.getTaskType()).parseResult(comfyUIService.getRes(taskEntity.getTaskPid(), taskEntity), parseConfig);
            if (taskResult != null) {
                taskEntity.setTaskResult(JSONUtil.toJsonStr(taskResult));
                if (taskResult.isFinished()) {
                    taskEntity.setTaskStatus(COMPLETE);
                }
                updateFlag = true;
            } else {
                taskResult = new TaskResult().setFinished(false).setOrderNum(taskEntity.getOrderNum());
                taskResult.setFinished(false);
            }
        } else if (taskEntity.getTaskStatus() == ERROR){
            taskResult = new TaskResult().setFinished(false).setOrderNum(taskEntity.getOrderNum())
                    .setError(true)
                    .setErrorMsg("任务执行异常，已关闭订单");
        }
        if (updateFlag) {
            saveOrUpdate(taskEntity);
            log.info("手动获取任务成功，内容为：{}", taskEntity.getTaskResult());
        }
        return taskResult;
    }

    /**
     * 组合结果
     *
     * @param taskResults 任务结果列表
     * @return 聚合结果
     */
    private TaskResult combineTaskResult(List<TaskResult> taskResults) {
        return new TaskResult().setFinished(taskResults.stream().allMatch(TaskResult::isFinished))
                .setOrderNum(taskResults.get(0).getOrderNum())
                .setTaskType(null)
                .setError(taskResults.stream().anyMatch(TaskResult::isError))
                .setErrorMsg(taskResults.stream().filter(TaskResult::isError).map(TaskResult::getErrorMsg).collect(Collectors.joining(",")))
                .setResultMap(taskResults.stream().map(TaskResult::getResultMap).reduce(new HashMap<>(), (m1, m2) -> {
                    m1.putAll(m2);
                    return m1;
                }));
    }

    @Override
    public SseEmitter getTaskProcess(String orderNum) {
        List<TaskEntity> taskEntities = list(new LambdaQueryWrapper<TaskEntity>().eq(TaskEntity::getOrderNum, orderNum).orderByDesc(TaskEntity::getId));
        if (taskEntities.isEmpty()) {
            throw new BizException("任务不存在");
        }
        List<Boolean> finishFlag = new ArrayList<>();
        // 新建任务sse
        SseEmitter sseTask = SseEmitterSender.getNewSseClient(orderNum);
        taskEntities.forEach(one -> {
            String clientId = "TASK-" + UserHandler.getLoginUser().getUserId() + "-" + one.getId();
            if (one.getTaskStatus() == COMPLETE) {
                finishFlag.add(true);
                SseEmitterSender.send(orderNum, "[result]:" + getTaskResult(one));
            } else {
                finishFlag.add(false);
                comfyUIService.getTaskProcessTracker(one, clientId, one.getTaskPid(), orderNum);
            }
        });
        if (finishFlag.stream().allMatch(t -> t)) {
            SseEmitterSender.complete(orderNum);
        }
        return sseTask;
    }

    private void submitTask(TaskEntity taskEntity, String taskParam) throws IOException {
        JSONObject workflow = jsonFileReader.readJsonFile(taskEntity.getTaskType());
        BaseOrderTaskHandler<?> orderTaskHandler = orderTaskHandlerHelper.getOrderTaskHandler(taskEntity.getTaskType(), taskParam);
        if (orderTaskHandler == null) {
            throw new BizException(taskEntity.getTaskType() + "未支持任务处理器解析");
        }
        workflow = orderTaskHandler.parseWorkflow(workflow);
        String clientId = "TASK-" + UserHandler.getLoginUser().getUserId() + "-" + taskEntity.getId();
        JSONObject requestJson = new JSONObject();
        requestJson.set("prompt", workflow);
        requestJson.set("client_id", clientId);
        comfyUIService.doTask(requestJson.toString(), taskEntity, clientId);
    }
}
